package com.irixel.hdc.controllers;

import java.io.StringWriter;
import java.security.Principal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.JsonGenerator.Feature;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.irixel.hdc.dto.BeneficiarioDTO;
import com.irixel.hdc.dto.FacturaDTO;
import com.irixel.hdc.dto.TipoFacturaDTO;

@Controller
public class FacturaController {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private TipoFacturaController tipoFacturaController;
	
	@Autowired
	private BeneficiarioController beneficiarioController;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView index(Principal principal) {
		ModelAndView mav = new ModelAndView("index");

		List<TipoFacturaDTO> tipos = tipoFacturaController.getTipos();
		List<FacturaDTO> facturas = getFacturas(principal);
		List<BeneficiarioDTO> beneficiarios = beneficiarioController.getBeneficiarios(principal);

		ObjectMapper mapper = new ObjectMapper();
		mapper.getSerializationConfig().setSerializationInclusion(
				Inclusion.NON_NULL);
		mapper.configure(Feature.QUOTE_NON_NUMERIC_NUMBERS, true);
		mapper.configure(Feature.WRITE_NUMBERS_AS_STRINGS, true);

		StringWriter sWriter = new StringWriter();
		try {
			mapper.writeValue(sWriter, tipos);
			mav.addObject("tipos", JSONObject.quote(sWriter.toString()));
		} catch (Exception e) {
			e.printStackTrace();
		}

		sWriter = new StringWriter();
		try {
			mapper.writeValue(sWriter, facturas);
			mav.addObject("facturas", JSONObject.quote(sWriter.toString()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		sWriter = new StringWriter();
		try {
			mapper.writeValue(sWriter, beneficiarios);
			mav.addObject("beneficiarios", JSONObject.quote(sWriter.toString()));
		} catch (Exception e) {
			e.printStackTrace();
		}

		return mav;
	}

	@RequestMapping(value = "/facturas", method = RequestMethod.GET)
	public @ResponseBody
	List<FacturaDTO> getFacturas(Principal principal) {
		List<FacturaDTO> facturas = jdbcTemplate
				.query("select factura.* from factura, users where ISNULL(fechaRendicion) and factura.id_user = users.id and users.username = ?",
						new Object[] { principal.getName() },
						new RowMapper<FacturaDTO>() {

							@Override
							public FacturaDTO mapRow(ResultSet rs, int rowNum)
									throws SQLException {
								FacturaDTO ret = new FacturaDTO();
								ret.setId(rs.getLong("id"));
								ret.setFecha(new Date(rs.getDate("fecha")
										.getTime()));
								ret.setDescripcion(rs.getString("descripcion"));
								ret.setMonto(rs.getDouble("monto"));
								ret.setNumFactura(rs.getString("numFactura"));
								ret.setIdTipo(rs.getLong("tipo"));
								ret.setBeneficiario(rs
										.getString("beneficiario"));
								ret.setRut(rs.getString("rut"));
								ret.setTelf(rs.getString("telf"));

								return ret;
							}

						});

		return facturas;
	}

	@RequestMapping(value = "/facturas", method = RequestMethod.POST)
	public @ResponseBody
	FacturaDTO createFactura(@RequestBody FacturaDTO factura,
			Principal principal) {
		Long userId = jdbcTemplate.queryForLong(
				"select id from users where username = ?", principal.getName());
		SimpleJdbcInsert insert = new SimpleJdbcInsert(
				jdbcTemplate.getDataSource()).withTableName("factura")
				.usingGeneratedKeyColumns("id");
		Map<String, Object> args = new HashMap<String, Object>();
		args.put("monto", factura.getMonto());
		args.put("fecha", factura.getFecha());
		args.put("descripcion", factura.getDescripcion());
		args.put("tipo", factura.getIdTipo());
		args.put("numFactura", factura.getNumFactura());
		args.put("id_user", userId);
		args.put("beneficiario", factura.getBeneficiario());
		args.put("rut", factura.getRut());
		args.put("telf", factura.getTelf());

		Number key = insert.executeAndReturnKey(args);
		factura.setId(key.longValue());
		return factura;
	}

	@RequestMapping(value = "/facturas", method = RequestMethod.PUT)
	public @ResponseBody
	FacturaDTO updateFactura(@RequestBody FacturaDTO factura) {
		jdbcTemplate
				.update("update factura set monto = ?, fecha = ?, descripcion = ?, numFactura = ?, tipo = ?, beneficiario = ?, rut = ?, telf = ? where id = ?",
						factura.getMonto(), factura.getFecha(),
						factura.getDescripcion(), factura.getNumFactura(),
						factura.getIdTipo(), factura.getBeneficiario(),
						factura.getRut(), factura.getTelf(), factura.getId());
		return factura;
	}

	@RequestMapping(value = "/facturas", method = RequestMethod.DELETE)
	public @ResponseBody
	String deleteFactura(@RequestParam("id") Long id) {
		jdbcTemplate.update("delete from factura where id = ?", id);
		return "";
	}

	@RequestMapping(value = "/facturas/rendir", method = RequestMethod.PUT)
	public @ResponseBody
	String rendirFacturas(Principal principal) {
		Long userId = jdbcTemplate.queryForLong(
				"select id from users where username = ?", principal.getName());
		jdbcTemplate
				.update("update factura set fechaRendicion = ? where ISNULL(fechaRendicion) and factura.id_user = ?",
						new Date(), userId);
		return "";
	}

}
